package com.michael.ims.admin.controller;


import com.michael.common.utils.Assert;
import com.michael.ims.admin.controller.io.user.*;
import com.michael.ims.app.*;
import com.michael.io.*;
import com.michael.plugins.PageHelper;
import com.michael.plugins.id.IdGenerator;
import com.michael.plugins.security.PasswordEncoder;
import com.querydsl.core.types.Projections;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;

@Api(tags = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private SQLQueryFactory sqlQueryFactory;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IdGenerator uuidIdGenerator;

    @ApiOperation("用户查询")
    @PostMapping("/query")
    @Transactional
    public RespData<RespPageBody<QueryUserVO>> query(@RequestBody @Valid ReqPage<QueryUserCond> req) {
        QueryUserCond cond = req.getCondition();

        QTblUser tblUser = QTblUser.tblUser;

        SQLQuery<QueryUserVO> sqlQuery = sqlQueryFactory.select(Projections.bean(QueryUserVO.class, tblUser.id, tblUser.account, tblUser.name, tblUser.email, tblUser.phone, tblUser.genTime))
                .from(tblUser);

        if (cond.getSystemId() != null) {
            QTblUserToSystem tblUserToSystem = QTblUserToSystem.tblUserToSystem;
            sqlQuery.join(tblUserToSystem)
                    .where(tblUserToSystem.systemId.eq(cond.getSystemId())
                            .and(tblUserToSystem.userId.eq(tblUser.id)));
        }
        if (StringUtils.isNotBlank(cond.getAccount())) {
            sqlQuery.where(tblUser.account.contains(cond.getAccount()));
        }

        if (cond.getRoleId() != null) {
            QTblUserToRole tblUserToRole = QTblUserToRole.tblUserToRole;
            sqlQuery.join(tblUserToRole)
                    .where(tblUser.id.eq(tblUserToRole.userId)
                            .and(tblUserToRole.roleId.eq(cond.getRoleId())));
        }

        if (StringUtils.isNotBlank(cond.getName())) {
            sqlQuery.where(tblUser.name.contains(cond.getName()));
        }
        PageHelper.Page<QueryUserVO> page = PageHelper.buildPage(req.getPage());
        PageHelper.execute(sqlQuery);

        RespPageBody<QueryUserVO> body = new RespPageBody<>();
        body.setPage(page.getPage());
        body.setData(page.getData());

        RespData<RespPageBody<QueryUserVO>> resp = new RespData<>();
        resp.setBody(body);
        return resp;
    }

    @ApiOperation("修改用户信息")
    @PostMapping("/modify")
    @Transactional
    @Deprecated
    public RespStatus modify(@RequestBody @Valid ModifyUserReq req) {
        QTblUser tblUser = QTblUser.tblUser;
        long result = sqlQueryFactory.update(tblUser)
                .set(tblUser.name, req.getName())
                .set(tblUser.email, req.getEmail())
                .set(tblUser.phone, req.getPhone())
                .where(tblUser.id.eq(req.getId()))
                .execute();

        Assert.notEqual("1", String.valueOf(result), "100001");
        return new RespStatus();
    }

    @ApiOperation("重置密码")
    @PostMapping("/reset")
    @Transactional
    public RespStatus reset(@RequestBody @Valid ResetUserReq req) {
        QTblUser tblUser = QTblUser.tblUser;
        long result = sqlQueryFactory.update(tblUser)
                .set(tblUser.password, passwordEncoder.encode("123456"))
                .where(tblUser.id.eq(req.getId()))
                .execute();
        Assert.notEqual("1", String.valueOf(result), "100001");
        return new RespStatus();
    }

    @ApiOperation("添加用户")
    @PostMapping("/add")
    @Transactional
    public RespStatus add(@RequestBody @Valid AddUserReq req) {
        QTblUser tblUser = QTblUser.tblUser;
        long result = sqlQueryFactory.insert(tblUser)
                .set(tblUser.account, req.getAccount())
                .set(tblUser.uuid, uuidIdGenerator.generate())
                .set(tblUser.password, passwordEncoder.encode("123456"))
                .set(tblUser.name, req.getName())
                .set(tblUser.email, req.getEmail())
                .set(tblUser.phone, req.getPhone())
                .set(tblUser.genTime, LocalDate.now())
                .execute();
        Assert.notEqual("1", String.valueOf(result), "100002");
        return new RespStatus();
    }

    @ApiOperation("删除用户")
    @PostMapping("/delete")
    @Transactional
    public RespStatus delete(@RequestBody @Valid DeleteUserReq req) {
        QTblUser tblUser = QTblUser.tblUser;
        sqlQueryFactory.delete(tblUser)
                .where(tblUser.id.eq(req.getId()))
                .execute();
        return new RespStatus();
    }

    @ApiOperation("角色维护")
    @PostMapping("/maintain/role")
    @Transactional
    public RespStatus maintainRole(@RequestBody @Valid MaintainUserRoleReq req) {
        //校验是否拥有该系统的访问权限
        QTblUserToSystem tblUserToSystem = QTblUserToSystem.tblUserToSystem;
        Long exist = sqlQueryFactory.select(tblUserToSystem.id)
                .from(tblUserToSystem)
                .where(tblUserToSystem.systemId.eq(req.getSystemId())
                        .and(tblUserToSystem.userId.eq(req.getUserId())))
                .fetchOne();
        Assert.isNull(exist, "100003");
        QTblUserToRole tblUserToRole = QTblUserToRole.tblUserToRole;
        //添加该用户下的该系统所拥有的角色
        sqlQueryFactory.insert(tblUserToRole)
                .set(tblUserToRole.systemId, req.getSystemId())
                .set(tblUserToRole.userId, req.getUserId())
                .set(tblUserToRole.roleId, req.getRoleId())
                .execute();
        return new RespStatus();
    }

    @ApiOperation("角色维护")
    @GetMapping("/maintain/role/{id}")
    @Transactional
    public RespStatus maintainRole(@PathVariable("id") Long id) {
        QTblUserToRole tblUserToRole = QTblUserToRole.tblUserToRole;
        //删除该用户下的该系统所拥有的角色
        sqlQueryFactory.delete(tblUserToRole)
                .where(tblUserToRole.id.eq(id))
                .execute();
        return new RespStatus();
    }

    @ApiOperation("系统维护")
    @PostMapping("/maintain/system")
    @Transactional
    public RespStatus maintainSystem(@RequestBody @Valid MaintainUserSystemReq req) {
        QTblUserToSystem tblUserToSystem = QTblUserToSystem.tblUserToSystem;
        //添加该用户下的该系统所拥有的角色
        sqlQueryFactory.insert(tblUserToSystem)
                .set(tblUserToSystem.systemId, req.getSystemId())
                .set(tblUserToSystem.userId, req.getUserId())
                .set(tblUserToSystem.isManager, false)
                .execute();
        return new RespStatus();
    }

    @ApiOperation("系统维护")
    @GetMapping("/maintain/system/{id}")
    @Transactional
    public RespStatus maintainSystem(@PathVariable("id") Long id) {
        QTblUserToSystem tblUserToSystem = QTblUserToSystem.tblUserToSystem;
        //删除该用户下的该系统的访问权限
        sqlQueryFactory.delete(tblUserToSystem)
                .where(tblUserToSystem.id.eq(id))
                .execute();
        return new RespStatus();
    }

    @ApiOperation("查询该用户下的角色列表")
    @PostMapping("/maintain")
    @Transactional
    public RespData<RespPageBody<MaintainUserVO>> maintainUser(@RequestBody @Valid ReqPage<MaintainUserReq> req) {
        MaintainUserReq condition = req.getCondition();
        PageHelper.Page<MaintainUserVO> page = PageHelper.buildPage(req.getPage());

        QTblUserToSystem tblUserToSystem = QTblUserToSystem.tblUserToSystem;
        QTblUserToRole tblUserToRole = QTblUserToRole.tblUserToRole;
        QTblRole tblRole = QTblRole.tblRole;
        QTblSystem tblSystem = QTblSystem.tblSystem;
        SQLQuery<MaintainUserVO> sqlQuery = sqlQueryFactory.select(Projections.bean(MaintainUserVO.class,
                tblUserToSystem.id.as("userToSystemId"), tblSystem.name.as("systemName"), tblSystem.desc.as("systemDesc"),
                tblUserToRole.id.as("userToRoleId"), tblRole.name.as("roleName"), tblRole.description.as("roleDesc")
        ))
                .from(tblUserToRole).join(tblUserToSystem).join(tblRole).join(tblSystem)
                .where(tblUserToRole.systemId.eq(tblUserToSystem.systemId)
                        .and(tblUserToRole.userId.eq(tblUserToSystem.userId))
                        .and(tblUserToRole.userId.eq(condition.getUserId()))
                        .and(tblUserToRole.systemId.eq(tblRole.systemId))
                        .and(tblUserToRole.roleId.eq(tblRole.id))
                        .and(tblUserToSystem.systemId.eq(tblSystem.id))
                        .and(tblUserToSystem.systemId.eq(tblSystem.id))
                        .and(tblSystem.isDelete.isFalse())
                );
        if (condition.getSystemId() != null) {
            sqlQuery.where(tblUserToSystem.systemId.eq(condition.getSystemId()));
        }
        PageHelper.execute(sqlQuery);
        RespPageBody<MaintainUserVO> body = new RespPageBody<>();
        body.setData(page.getData());
        body.setPage(page.getPage());
        RespData<RespPageBody<MaintainUserVO>> resp = new RespData();
        resp.setBody(body);
        return resp;
    }
}
